#include <iostream>
#include <string>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>

#include "Nocopy.hpp"

using std::cout;
using std::endl;
static const int gsockfd = -1;
static const uint16_t glocalport = 8888;

class UdpServer : public nocopy
{

public:
    UdpServer(uint16_t localport = glocalport)
    :_localport(localport),_sockfd(gsockfd),_isrunning(false)
    {}

    void InitServer()
    {
        // 创建套接字
        _sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (_sockfd < 0)
        {
            cout << "FATAL: sockfd error" << endl;
            exit(1);
        }
        cout << "DEBUG: sockfd success" << endl;
        // 填充数据
        struct sockaddr_in local;
        memset(&local, 0, sizeof(local));   // clean sockaddr_in
        local.sin_family = AF_INET;         // 地址族
        local.sin_port = htons(_localport); // 端口号
        // local.sin_addr.s_addr = inet_addr(_localip.c_str());
        local.sin_addr.s_addr = INADDR_ANY; // ip地址
        // bind
        int n = bind(_sockfd, (sockaddr *)&local, sizeof(local));
        if (n < 0)
        {
            cout << "FATAL: bind error" << endl;
            exit(1);
        }
        cout << "DEBUG: bind success" << endl;
    }

     void start()
    {
        _isrunning = true;
        char inbuffer[1024];
        while (_isrunning)
        {
            struct sockaddr_in peer;
            socklen_t len = sizeof(peer);
            ssize_t n = recvfrom(_sockfd, inbuffer, sizeof(inbuffer) - 1, 0, (struct sockaddr *)&peer, &len);
            if (n > 0)
            {
                inbuffer[n] = 0;
                
                std::cout << "[" <<  inet_ntoa(peer.sin_addr) << ":" << ntohs(peer.sin_port) << "]# " << inbuffer << std::endl;

                std::string echo_string = "[udp_server echo] #";
                echo_string += inbuffer;
                sendto(_sockfd, echo_string.c_str(), echo_string.size(), 0, (struct sockaddr *)&peer, len);
            }
            else
            {
                std::cout << "recvfrom error"  << std::endl;
                _isrunning = false;
            }
        }
    }

    ~UdpServer() 
    {
        if(_sockfd > gsockfd) 
        ::close(_sockfd);
    }

private:
    int _sockfd;          // 套接字socket
    uint16_t _localport;  // 端口号
    // std::string _localip; // ip地址
    bool _isrunning;
};
